﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geoprocessor;

namespace ArcMap_AddIn_Tools
{
    public partial class FeatureclassToShapefileForm : Form
    {
        #region 自定义变量
        private string[] ColumnNames = new string[] { "源数据要素类名称", "目标数据导出shp名称" };
        private DataTable dt = new DataTable();
        private IMxDocument mxDocument = ArcMap.Document;
        private List<IFeatureClass> M_FeatureClass = new List<IFeatureClass>();
        string statusBarInfo = "";

        #endregion

        #region 事件
        public FeatureclassToShapefileForm()
        {
            InitializeComponent();
            this.dataGridView1.DataSource = dt;
        }

        /// <summary>
        /// 导出shp
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonExportShp_Click(object sender, EventArgs e)
        {
            try
            {
                bool executeed = ExportShp();
                if (executeed == true)
                {
                    MessageBox.Show("执行完成！");
                    this.Close();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("导出有错误！");
                this.Close();
                return;
            }
        }

        /// <summary>
        /// 加载窗体
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ExportInfoForm_Load(object sender, EventArgs e)
        {
            LoadTable();
            try
            {
                // 行头隐藏
                this.dataGridView1.RowHeadersVisible = false;
                // 禁止用户修改第一列
                this.dataGridView1.Columns[0].ReadOnly = true;
                this.dataGridView1.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                this.dataGridView1.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            }
            catch (Exception ex)
            {
                return;
            }
        }


        private void buttonExportPath_Click(object sender, EventArgs e)
        {
            string inShpPath = "";
            FolderBrowserDialog outputDialog = new FolderBrowserDialog();
            if (outputDialog.ShowDialog() == DialogResult.OK)
            {
                inShpPath = outputDialog.SelectedPath;
                this.textBoxShpPath.Text = inShpPath;
            }
        }

        /// <summary>
        /// 取消
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        #endregion

        #region 方法
        /// <summary>
        /// 创建表，有列名，无数据
        /// </summary>
        /// <param name="TableName"></param>
        /// <param name="ColumnNames"></param>
        /// <returns></returns>
        private DataTable CreateTable(string[] ColumnNames)
        {
            for (int i = 0; i < ColumnNames.Length; i++)
            {
                string columnName = ColumnNames[i];
                DataColumn dc = new DataColumn();
                dc.DataType = System.Type.GetType("System.String");
                dc.Caption = columnName;
                dc.ColumnName = columnName;
                dt.Columns.Add(dc);
            }

            return dt;
        }

        private void LoadTable()
        {
            dt = CreateTable(ColumnNames);
            IMap pMap = mxDocument.FocusMap;
            if (pMap.LayerCount == 0)
                return;
            int num = 0;
            for (int i = 0; i < pMap.LayerCount; i++)
            {
                ILayer layer = pMap.get_Layer(i);
                if (layer.Visible == false)
                    continue;
                GetLayerInfo(layer, ref num);
            }
        }

        /// <summary>
        /// 遍历地图视图，获取图层
        /// </summary>
        /// <param name="pLayer"></param>
        public void GetLayerInfo(ILayer Layer, ref int i)
        {
            if (Layer as IFeatureLayer != null)
            {

                IFeatureLayer featureLayer = Layer as IFeatureLayer;
                IFeatureClass featureClass = featureLayer.FeatureClass;
                string featureClassName = ((IDataset)featureClass).Name;
                dt.Rows.Add();
                dt.Rows[i][ColumnNames[0]] = featureClassName;
                dt.Rows[i][ColumnNames[1]] = featureClassName;
                M_FeatureClass.Add(featureClass);
                i++;
            }
            else
            {
                if (Layer is IGroupLayer)
                {
                    ICompositeLayer pCompositeLayer = Layer as ICompositeLayer;
                    for (int j = 0; j < pCompositeLayer.Count; j++)
                    {
                        GetLayerInfo(pCompositeLayer.get_Layer(j), ref i);
                    }
                }
            }
        }

        private bool ExportShp()
        {
            bool executeed = false;
            string shpFilePath = this.textBoxShpPath.Text;
            if (Directory.Exists(shpFilePath) == false)
            {
                MessageBox.Show("保存路径不存在！");
                executeed = false;
                return executeed;
            }
            Dictionary<string, string> layerNames = GetDicNames();
            IMap pMap = mxDocument.FocusMap;
            for (int i = 0; i < M_FeatureClass.Count; i++)
            {
                IFeatureClass pFeatureClass = M_FeatureClass[i];
                string featureClassName = ((IDataset)pFeatureClass).Name;
                string shpFileName = layerNames[featureClassName];
                CreateShp(pFeatureClass, shpFilePath, shpFileName);
                //GeoprocessingExportSHPTool(@"数据库连接\Connection to OracleSDE.sde\SDE.CY_TDQS\SDE.CY_JZX", @"D:\shp", "TEST2.shp");
                statusBarInfo = string.Format("进度:{0}/{1};图层名：{2}.", i + 1, M_FeatureClass.Count, featureClassName);
                ArcMap.Application.StatusBar.set_Message(0, statusBarInfo);
                Application.DoEvents();
            }
            executeed = true;
            return executeed;
        }

        /// <summary>
        /// 从datagridview中获取名称
        /// </summary>
        /// <returns></returns>
        private Dictionary<string, string> GetDicNames()
        {
            if (IsHaveNull() == true)
            {
                MessageBox.Show("shpapefile文件名称有空的！");
                return null;
            }
            Dictionary<string, string> names = new Dictionary<string, string>();
            for (int i = 0; i < this.dataGridView1.RowCount; i++)
            {
                string featureClassName = dt.Rows[i][ColumnNames[0]].ToString();
                string shpName = dt.Rows[i][ColumnNames[1]].ToString();
                names.Add(featureClassName, shpName);
            }

            return names;
        }

        /// <summary>
        /// 判断datagridvies中是否有空数据
        /// </summary>
        /// <returns></returns>
        private bool IsHaveNull()
        {
            bool isHaveNull = false;
            for (int i = 0; i < this.dataGridView1.RowCount; i++)
            {
                for (int j = 0; j < this.dataGridView1.ColumnCount; j++)
                {
                    if (dt.Rows[i][ColumnNames[0]] == null)
                    {
                        isHaveNull = true;
                    }
                }
            }

            return isHaveNull;
        }

        /// <summary>
        /// 创建shp图层
        /// </summary>
        /// <param name="FeatureClass"></param>
        /// <param name="FilePath"></param>
        /// <param name="FileName"></param>
        private void CreateShp(IFeatureClass FeatureClass, string FilePath, string FileName)
        {
            IWorkspaceFactory pWorkspaceFactory = new ShapefileWorkspaceFactoryClass();
            IWorkspace pOutWorkspace = pWorkspaceFactory.OpenFromFile(FilePath, 0) as IWorkspace;
            IDataset pInDataset = FeatureClass as IDataset;
            IFeatureClassName pInFCName = pInDataset.FullName as IFeatureClassName;
            IWorkspace pInWorkspace = pInDataset.Workspace;
            IDataset pOutDataset = pOutWorkspace as IDataset;
            IWorkspaceName pOutWorkspaceName = pOutDataset.FullName as IWorkspaceName;
            IFeatureClassName pOutFCName = new FeatureClassNameClass();
            IDatasetName pDatasetName = pOutFCName as IDatasetName;
            pDatasetName.WorkspaceName = pOutWorkspaceName;
            pDatasetName.Name = FileName;
            IFieldChecker pFieldChecker = new FieldCheckerClass();
            pFieldChecker.InputWorkspace = pInWorkspace;
            pFieldChecker.ValidateWorkspace = pOutWorkspace;
            IFields pFields = FeatureClass.Fields;
            IFields pOutFields;
            IEnumFieldError pEnumFieldError;
            pFieldChecker.Validate(pFields, out pEnumFieldError, out pOutFields);
            IFieldsEdit fieldsEdit = pOutFields as IFieldsEdit;
            for (int i = 0; i < pOutFields.FieldCount; i++)
            {
                IField field = pOutFields.get_Field(i);
                if (field.Type == esriFieldType.esriFieldTypeBlob)
                {
                    fieldsEdit.DeleteField(pOutFields.get_Field(i));
                }
            }

            ISpatialReferenceFactory spatialReferenceFactory = new
    SpatialReferenceEnvironmentClass();
            ISpatialReference spatialReference =
                spatialReferenceFactory.CreateProjectedCoordinateSystem((int)
                esriSRProjCSType.esriSRProjCS_NAD1983UTM_20N);
            ISpatialReferenceResolution spatialReferenceResolution =
                (ISpatialReferenceResolution)spatialReference;
            spatialReferenceResolution.ConstructFromHorizon();
            spatialReferenceResolution.SetDefaultXYResolution();
            ISpatialReferenceTolerance spatialReferenceTolerance =
                (ISpatialReferenceTolerance)spatialReference;
            spatialReferenceTolerance.SetDefaultXYTolerance();

            ILayer layer = CreateFeatureLayerInmemeory("test", "test", spatialReference, FeatureClass.ShapeType, pOutFields);


            IFeatureDataConverter pFeatureDataConverter = new FeatureDataConverterClass();
            pFeatureDataConverter.ConvertFeatureClass(pInFCName, null, null, pOutFCName, null, pFields, "", 10000, 0);
        }

        /// <summary>
        /// 在内存中创建图层
        /// </summary>
        /// <param name="DataSetName">数据集名称</param>
        /// <param name="AliaseName">别名</param>
        /// <param name="SpatialRef">空间参考</param>
        /// <param name="GeometryType">几何类型</param>
        /// <param name="PropertyFields">属性字段集合</param>
        /// <returns>IfeatureLayer</returns>
        public static IFeatureLayer CreateFeatureLayerInmemeory(string DataSetName, string AliaseName, ISpatialReference SpatialRef, esriGeometryType GeometryType, IFields PropertyFields)
        {
            IWorkspaceFactory workspaceFactory = new InMemoryWorkspaceFactoryClass();
            ESRI.ArcGIS.Geodatabase.IWorkspaceName workspaceName = workspaceFactory.Create("", "MyWorkspace", null, 0);
            ESRI.ArcGIS.esriSystem.IName name = (IName)workspaceName;
            ESRI.ArcGIS.Geodatabase.IWorkspace inmemWor = (IWorkspace)name.Open();

            IField oField = new FieldClass();
            IFields oFields = new FieldsClass();
            IFieldsEdit oFieldsEdit = null;
            IFieldEdit oFieldEdit = null;
            IFeatureClass oFeatureClass = null;
            IFeatureLayer oFeatureLayer = null;

            try
            {
                oFieldsEdit = oFields as IFieldsEdit;
                oFieldEdit = oField as IFieldEdit;

                for (int i = 0; i < PropertyFields.FieldCount; i++)
                {
                    oFieldsEdit.AddField(PropertyFields.get_Field(i));
                }

                IGeometryDef geometryDef = new GeometryDefClass();
                IGeometryDefEdit geometryDefEdit = (IGeometryDefEdit)geometryDef;
                geometryDefEdit.AvgNumPoints_2 = 5;
                geometryDefEdit.GeometryType_2 = GeometryType;
                geometryDefEdit.GridCount_2 = 1;
                geometryDefEdit.HasM_2 = false;
                geometryDefEdit.HasZ_2 = false;
                geometryDefEdit.SpatialReference_2 = SpatialRef;

                oFieldEdit.Name_2 = "SHAPE";
                oFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
                oFieldEdit.GeometryDef_2 = geometryDef;
                oFieldEdit.IsNullable_2 = true;
                oFieldEdit.Required_2 = true;
                oFieldsEdit.AddField(oField);

                oFeatureClass = (inmemWor as IFeatureWorkspace).CreateFeatureClass(DataSetName, oFields, null, null, esriFeatureType.esriFTSimple, "SHAPE", "");
                (oFeatureClass as IDataset).BrowseName = DataSetName;

                oFeatureLayer = new FeatureLayerClass();
                oFeatureLayer.Name = AliaseName;
                oFeatureLayer.FeatureClass = oFeatureClass;
            }
            catch
            {
            }
            finally
            {
                try
                {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(oField);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(oFields);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldsEdit);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldEdit);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(name);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(workspaceFactory);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(workspaceName);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(inmemWor);
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(oFeatureClass);
                }
                catch { }

                GC.Collect();
            }
            return oFeatureLayer;
        }
        /// <summary>
        /// 裁剪
        /// </summary>
        /// <param name="In_Features"></param>
        /// <param name="Clip_Feature"></param>
        /// <param name="Out_Features_Class"></param>
        public void GeoprocessingExportSHPTool(string In_features, string Out_path, string Out_name)
        {
            try
            {
                // Create the geoprocessor. 
                Geoprocessor GP = new Geoprocessor();

                // Create the tool process object.
                ESRI.ArcGIS.ConversionTools.FeatureClassToFeatureClass tool = new ESRI.ArcGIS.ConversionTools.FeatureClassToFeatureClass();

                // Set parameter values.
                tool.in_features = In_features;
                tool.out_path = Out_path;
                tool.out_name = Out_name;
                // Execute the tool. 
                GP.Execute(tool, null);
            }
            catch (Exception ex)
            {

            }

        }

        #endregion
    }
}
